<?php
	require_once(dirname(__FILE__)."/incluir.php");
	require_once(dirname(__FILE__)."/dados.php");
	// ####################################
	// # Classe para representar um campo #
	// ####################################
	class Campo
	{
		// Dados do campo
		public $nome;
		public $tipo; // Os valores são: data, file, password, telefone, text, textarea, select, radio, checkbox, numero
		public $valor_default; 
		public $campo_multiplo;
		public $paginas_aparece; // Um array contendo as páginas que esse campo aparece
		public $label;
		
		// Dados de campos select, ou radio buttons, ou checkboxes
		public $valores;
		
		// Informações para o Banco de Dados
		public $tabela;
		private $sqlController;
		
		// Sufixo do nome, por exemplo: se o nome for "idade" e o sufixo for "_usuario", entao o nome completo ficaria idade_usuario
		public $sufixo;
		
		// Informações de validação
		public $mensagem_erro;
		private $validacoes;

		public function __construct($nome, $sufixo = '', $tipo = 'text', $label = null, $valor_default = '', $campo_multiplo = false, 
								$paginas_aparece = null,
								$validacoes = null,
								$tabela = null,
								$valores = null,
								$sqlController = null)
		{
			$this->nome = $nome;
			$this->sufixo = $sufixo;
			$this->tipo = $tipo;
			$this->valor_default = $valor_default;
			$this->campo_multiplo = $campo_multiplo;
			$this->valores = $valores;
			$this->paginas_aparece = (!is_array($paginas_aparece)) ? array('alterar', 'index', 'inserir', 'visualizar') : $paginas_aparece;
			
			// O valor default da label é o nome do campo com a primeira letra maiúscula
			$this->label = ($label == null) ? ucfirst($nome) : $label;
			
			$validacao_padrao = new Validacao($this->nome, $this->sufixo);
			$this->validacoes = ($validacoes == null) ? $validacao_padrao : $validacoes;
			
			$this->tabela = $tabela;
			
			if($sqlController == null) // se não foi passado uma instancia de um controlador de banco de dados, usa o de mysql
			{
				$this->sqlController = new MySQLController($this->tabela); // Crio um controlador que manipula a tabela passada
			}
			else
			{
				$this->sqlController = $sqlController;
			}
		}
		
		public function valida($dados)
		{
			if(is_array($this->validacoes))
			{
				foreach($this->validacoes as $validacao)
				{
					if(!$validacao->valida($dados)) // Se não validou com sucesso
					{
						$this->mensagem_erro = $validacao->mensagem_erro;
						return false;
					}
				}
			}
			else // Se for apenas uma validação
			{
				if(!$this->validacoes->valida($dados)) // Se não validou com sucesso
				{
					$this->mensagem_erro = $this->validacoes->mensagem_erro;
					return false;
				}
			}
			return true;
		}
		
		// $total_file_path será igual ao valor de __FILE__ passado em outras páginas
		public function pertence_pagina($total_file_path)
		{
			$file_name = basename($total_file_path, ".php");
			return in_array($file_name, $paginas_aparece); // diz se esse campo pertence página que quer visitar
		}
		
		public function get_mensagem_erro()
		{
			return $this->mensagem_erro;
		}
		
		
		// Pega todos os valores desse campo da tabela do viale
		public function get_all()
		{
			$classe = ucfirst($this->tabela); // a classe sempre é a tabela com a letra minuscula
			// Se não existe esse arquivo retorna null, indicando que não tem de onde pegar os dados
			if(!file_exists(dirname(__FILE__)."/../$this->tabela/dados.php"))
				return null;
				
			require_once(dirname(__FILE__)."/../$this->tabela/dados.php"); // pega os dados da entidade desse campo
			// Usa a referencia para saber por qual campo ordenar e qual campo adicionar ao select
			$rows = $this->sqlController->get_rows(array('id', $referencia), $this->tabela, null, $referencia, 'ASC');
			// Transforma o array com as chave sendo o id do campo (util para escrever um campo select)
			foreach($rows as $index => $row)
			{
				foreach($row as $value)
				{
					$rows[$index][$row['id']] = $value; // coloca uma chave indexada para os valores de cada linha
				}
			}
			return $rows;
		}
		
		// Pega um valor específico da tabela, dependendo do valor da variável $id passado
		public function get_row($id = null)
		{
			// Passa para pegar somente o id e o valor do campo
			return $this->sqlController->get_row($id, array('id', $this->nome), $this->tabela);
		}
		
		// Funções de campos em forms
		
		private function append_output(&$output,$value)
		{
			$output .= $value;
			$output .= "\n";
		}
		
		// Função auxiliar para a função visualizar, se o campo for um checkbox ou um radio button,
		// em vez de mostrar o valor que está no BD, mostra o valor que deve ser exibido
		private function get_valor_real($valor)
		{
			// Cada valor é um array, aonde o primeiro elemento é o valor que está no banco e o segundo é o valor que deve ser exibido na tela
			foreach($this->valores as $valor_array)
			{
				// Se encontrou em qual parte está o valor
				if($valor_array[0] == $valor)
				{
					return $valor_array[1];// Retorna o valor que deve ser exibido
				}
			}
			return $valor; // Se não encontrou nada, retorna o próprio valor passado
		}
		
		// Escreve html para visualização do campo
		public function visualizar($valor, $escreve_na_tela = true)
		{
			$valor = (!isset($valor)) ? "Campo não preenchido" : $valor;
			$final_nome = substr($field, -4); // Pega os últimos 3 caracteres do nome do campo

			// Se esse campo é para relacionar com outra tabela
			if($tipo_campo == 'select' && $final_nome == '_id')
			{
				// Pego a linha da tabela cujo id está nesse campo
				$factory = new Factory();
				$model = $factory->cria_instancia_model($this->tabela);
				$row = $model->get_row($valor); // Aqui $valor vale o id, por isso pego a linha do BD com id $valor
				$output = (!$escreve_na_tela) ? "&nbsp;" : "<br />"; // Se não for para escrever na tela, não pula linha
				$output .= "Registro da tabela $this->tabela cujo id vale $valor:<br />\n";
				// Escrevo o visualizar do registro dessa tabela
				foreach($row as $field => $valor)
				{
					//Se o campo não deve ser mostrado passa para o próximo
					$campo = $model->campos[$field];
					if(!in_array('visualizar', $campo->paginas_aparece)) continue;
					$this->append_output($output, "&nbsp;".$campo->visualizar($valor, false));
				}
			}
			else if($this->tipo == "checkbox" || $this->tipo == "radio" || $this->tipo == "select")
			{
				$valor_real = $this->get_valor_real($valor);
				$this->append_output($output, "<span class=\"label_campo\">$this->label:</span><span class=\"valor_campo\"> $valor_real </span><br />");
			}
			else
			{
				// Se o campo tiver sido preenchido por uma textarea, os seus \n tem que ser substituidos por tags <br />, para mostrar corretamente o seu valor
				if($this->tipo == "textarea")
				{
					$valor = str_replace("\n", "<br />", $valor);
					$valor = "<br />".$valor; // manda pular uma linha depois da label e antes do valor, para ser exibido melhor
				}
				$this->append_output($output, "<span class=\"label_campo\">$this->label:</span><span class=\"valor_campo\"> $valor </span><br />");
			}
			if($escreve_na_tela) echo $output;
			return $output;
		}
		
		protected function escreve_info_campo_multiplo(&$output)
		{
			$this->append_output($output, '<a id="excluir_entidade_'.$this->tabela.'" name="excluir_entidade_'.$this->tabela.'" class="excluir_entidade" href="#">Excluir '.$this->tabela.'</a><br />');
			$this->append_output($output, '<a id="adiciona_'.$this->nome.'" name="adiciona_'.$this->nome.'" class="adicionar_entidade" href="#">Adicionar '.$this->tabela.'</a>');
		}
	
		// Escreve um campo do tipo input
		public function escreve_html_textarea($escreve_na_tela = true, $adiciona_label = true, $adiciona_erro = true, $adiciona_valor = true)
		{
			$output = "";
			$nome_controller = '$'.$this->tabela.'_controller'; // O nome do controller que será usado para escrever as mensagens de erro
			
			// Se for para escrever o valor do campo $adiciona_valor valerá true, se não o valor do campo será vazio
			$id_nome = $this->nome.$this->sufixo; // guardará o valor do atributo id e do atributo nome
			$value = ($adiciona_valor) ? '<?php echo isset($_POST[\''.$id_nome.'\']) ? $_POST[\''.$id_nome.'\'] : '.$nome_controller.'->model->'.$this->nome.'; ?>' : ''; 
			
			if($adiciona_label)
			{
				$this->append_output($output, '<label for="'.$id_nome.'">'.$this->label.'</label><br />');
			}
			
			$this->append_output($output, '<textarea id="'.$id_nome.'" name="'.$id_nome.'" value="'.$value.'" ></textarea><br />');

			// Coloca a linha que escreve o erro que o campo teve
			if($adiciona_erro)
			{
				$this->append_output($output, '<?php $site->print_erro('.$nome_controller.'->erros["'.$this->nome.'"]); ?>');
			}
			
			if($escreve_na_tela) echo $output;
			
			if($this->campo_multiplo) $this->escreve_info_campo_multiplo(&$output);
			
			return $output;
		}
		
		
		public function escreve_html_input($escreve_na_tela = true, $adiciona_label = true, $adiciona_erro = true, $adiciona_valor = true)
		{
			$output = "";
			$nome_controller = '$'.$this->tabela.'_controller'; // O nome do controller que será usado para escrever as mensagens de erro
			
			if($this->tipo == "telefone" || $this->tipo == "data")
				$escreve_class = 'class="'.$this->tipo.'"';
			
			// Data e Telefones são input type="text"
			if ($this->tipo == "data" || $this->tipo == "telefone" ) $tipo = "text";
			else $tipo = $this->tipo;
			// Se for para escrever o valor do campo $adiciona_valor valerá true e não será um campo senha, se não o valor do campo será vazio
			$id_nome = $this->nome.$this->sufixo; // guardará o valor do atributo id e do atributo nome
			
			// Avalia os casos especiais de data e password
			if($this->tipo == "data")
				$value = '<?php echo isset($_POST[\''.$id_nome.'\']) ? $_POST[\''.$id_nome.'\'] : $site->data_normal('.$nome_controller.'->model->'.$this->nome.'); ?>';
			else if($this->tipo != "password")
				$value = '<?php echo isset($_POST[\''.$id_nome.'\']) ? $_POST[\''.$id_nome.'\'] : '.$nome_controller.'->model->'.$this->nome.'; ?>';

			$value = ($adiciona_valor) ? $value : ''; 
			
			if($adiciona_label)
			{
				$this->append_output($output, '<label for="'.$id_nome.'">'.$this->label.'</label><br />');
			}
			
			$this->append_output($output, '<input type="'.$tipo.'" id="'.$id_nome.'" name="'.$id_nome.'" value="'.$value.'" '.$escreve_class.' /><br />');

			// Coloca a linha que escreve o erro que o campo teve
			if($adiciona_erro)
			{
				$this->append_output($output, '<?php $site->print_erro('.$nome_controller.'->erros["'.$this->nome.'"]); ?>');
			}
			
			if($escreve_na_tela) echo $output;
			
			if($this->campo_multiplo) $this->escreve_info_campo_multiplo(&$output);
			
			return $output;
		}

		public function escreve_html_select($escreve_na_tela = true, $adiciona_label = true, $adiciona_erro = false, $valores = null, $multiple = false, $selected_val = null)
		{
			$output = "";
			$nome_controller = '$'.$this->tabela.'_controller'; // O nome do controller que será usado para escrever as mensagens de erro
			$selected_id = isset($selected_id) ? $selected_id : 0; // O valor default é deixar o primeiro selecionado	
			
			$id = $this->nome.$this->sufixo; // guardará o valor do atributo id
			$nome = ($this->campo_multiplo) ? $id.'[]' : $id; // Coloca um [] se for um campo multiplo
			
			if($adiciona_label)
			{
				$this->append_output($output, '<label for="'.$nome.'">'.$this->label.'</label><br />');
			}
			
			$multiple_text = ($multiple) ? 'multiple="multiple"' : '';
						
			$this->append_output($output, '<select id="'.$id.'" name="'.$nome.'" '.$multiple_text.' >');
			
			// Se não tem nada nos valores do campo
			if(!isset($this->valores))
			{
				$this->valores = isset($valores) ? $valores : $this->get_all(); // Se já tinha valores, deixa assim
			}
			
			// Coloca a parte de Options
			$index = 0; // guarda qual a opção que está sendo escrita
			foreach($this->valores as $id => $valor)
			{
				$valor_real = $valor[0];
				$valor_mostrado = $valor[1];
				$selected_text = ($valor_real == $selected_val) ? 'selected="selected"' : '';
				$this->append_output($output, '<option value="'.$valor_real.'" '.$selected_text.'>'.$valor_mostrado.'</option>');
				$index++;
			}
			$this->append_output($output, '</select><br />');
			
			// Coloca a linha que escreve o erro que o campo teve
			if($adiciona_erro)
			{
				$this->append_output($output, '<?php $site->print_erro('.$nome_controller.'->erros["'.$this->nome.'"]);?>');
			}
			
			if($escreve_na_tela) echo $output;
			
			if($this->campo_multiplo) $this->escreve_info_campo_multiplo(&$output);
			
			return $output;
		}
		
		public function escreve_html_checkbox($escreve_na_tela = true, $adiciona_label = true, $adiciona_erro = true, $valores = null, $selected_val = null)
		{
			$output = "";
			$nome_controller = '$'.$this->tabela.'_controller'; // O nome do controller que será usado para escrever as mensagens de erro
			
			$primeiro_valor_real = $this->valores[0][0]; // O primeiro valor real possivel
			$selected_val = isset($selected_val) ? $selected_val : $primeiro_valor_real; // O valor default é deixar o primeiro selecionado
			
			$id_nome = $this->nome.$this->sufixo; // guardará o valor do atributo id e do atributo nome
			
			if($adiciona_label)
			{
				$this->append_output($output, '<label for="'.$id_nome.'">'.$this->label.'</label><br />');
			}
			
			$this->valores = isset($valores) ? $valores : $this->valores;
			
			foreach($this->valores as $valor)
			{
				$valor_real = $valor[0];
				$valor_mostrado = $valor[1];
				$selected_text = ($valor_real == $selected_val) ? 'checked="checked"' : '';
				$this->append_output($output, '<input type="checkbox" id="'.$id_nome.'" name="'.$id_nome.'" value="'.$valor_real.'"'.$selected_text.'/><span id="'.$id_nome.'_mostrado">'.$valor_mostrado.'</span><br />');
			}
			
			// Coloca a linha que escreve o erro que o campo teve
			if($adiciona_erro)
			{
				$this->append_output($output, '<?php $site->print_erro('.$nome_controller.'->erros["'.$this->nome.'"]);?>');
			}
			
			if($escreve_na_tela) echo $output;
			
			if($this->campo_multiplo) $this->escreve_info_campo_multiplo(&$output);
			
			return $output;
		}
		
		public function escreve_html_radio($escreve_na_tela = true, $adiciona_label = true, $adiciona_erro = true, $valores = null, $selected_val = null)
		{
			$output = "";
			$nome_controller = '$'.$this->tabela.'_controller'; // O nome do controller que será usado para escrever as mensagens de erro
			
			$primeiro_valor_real = $this->valores[0][0]; // O primeiro valor real possivel
			$selected_val = isset($selected_val) ? $selected_val : $primeiro_valor_real; // O valor default é deixar o primeiro selecionado
			
			$id_nome = $this->nome.$this->sufixo; // guardará o valor do atributo id e do atributo nome
			
			if($adiciona_label)
			{
				$this->append_output($output, '<label for="'.$id_nome.'">'.$this->label.'</label><br />');
			}
			
			$this->valores = isset($valores) ? $valores : $this->valores;
			
			// Os elementos do array com os valores estará no formato array(valor_real, valor_mostrado)
			foreach($this->valores as $valor)
			{
				$valor_real = $valor[0];
				$valor_mostrado = $valor[1];
				$selected_text = ($valor_real == $selected_val) ? 'checked="checked"' : '';
				$this->append_output($output, '<input type="radio" id="'.$id_nome.'" name="'.$id_nome.'" value="'.$valor_real.'"'.$selected_text.'/><span id="'.$id_nome.'_mostrado">'.$valor_mostrado.'</span><br />');
			}
			
			// Coloca a linha que escreve o erro que o campo teve
			if($adiciona_erro)
			{
				$this->append_output($output, '<?php $site->print_erro('.$nome_controller.'->erros["'.$this->nome.'"]);?>');
			}
			
			if($escreve_na_tela) echo $output;
			
			if($this->campo_multiplo) $this->escreve_info_campo_multiplo(&$output);
			
			return $output;
		}
		
		public function escreve_html($escreve_na_tela = true, $adiciona_label = true, $adiciona_erro = true, $adiciona_valor = true)
		{
			$output = '';
			
			if($this->tipo == "textarea")
			{
				$output = $this->escreve_html_textarea($escreve_na_tela, $adiciona_label, $adiciona_erro, $adiciona_valor);
			}
			else if($this->tipo == "select")
			{
				$output = $this->escreve_html_select($escreve_na_tela, $adiciona_label);
			}
			else if($this->tipo == "checkbox")
			{
				$output = $this->escreve_html_checkbox($escreve_na_tela, $adiciona_label);
			}
			else if($this->tipo == "radio")
			{
				$output = $this->escreve_html_radio($escreve_na_tela, $adiciona_label);
			}
			else
			{
				$output = $this->escreve_html_input($escreve_na_tela, $adiciona_label, $adiciona_erro, $adiciona_valor);
			}
			
			return $output;
		}
	}

?>